package utils

import (
	"encoding/binary"
	"encoding/json"
	"fmt"
	"net"

	"github.com/clebeg/gochat/protocol"
)

const (
	MaxLenMsg = 1024
)

type Transfer struct {
	Conn    net.Conn
	DataBuf [MaxLenMsg]byte
}

// 通过socket接收消息，并且反序列化为消息结构体，并且验证消息长度
func (t *Transfer) ReceiveMsg() (msg protocol.Message, err error) {
	// 先读取数据4个字节，获取下一步读取数据的长度信息
	n, err := t.Conn.Read(t.DataBuf[:4])
	if n != 4 {
		err = fmt.Errorf("传输的长度=%d", n)
		return
	}
	if err != nil {
		err = fmt.Errorf("传输的长度信息错误，错误信息：%v", err)
		return
	}
	hopeSize := binary.LittleEndian.Uint32(t.DataBuf[:4])
	realSize, err := t.Conn.Read(t.DataBuf[:hopeSize])
	if uint32(realSize) != hopeSize {
		err = fmt.Errorf("传输的数据长度错误，希望长度=%d，实际长度=%d", hopeSize, realSize)
		return
	}
	if err != nil {
		err = fmt.Errorf("传输的数据错误，错误信息：%v", err)
		return
	}
	readMsg := t.DataBuf[:realSize]
	msg = protocol.Message{}
	err = json.Unmarshal(readMsg, &msg)
	if err != nil {
		err = fmt.Errorf("json.Unmarshal(readMsg, msg) err, %v", err)
		return
	}
	return
}

func (t *Transfer) SendMsg(jsonBytes []byte, msgType string) (err error) {

	msg := protocol.Message{
		MsgType: msgType,
		MsgData: string(jsonBytes),
	}

	byteMsg, err := json.Marshal(msg)
	if err != nil {
		err = fmt.Errorf("json.Marshal(msg) err, %v", err)
		return
	}

	realSize := len(byteMsg)
	if realSize > MaxLenMsg {
		err = fmt.Errorf("超过发送消息的最大长度限制, 最大长度:%d, 实际长度:%d", MaxLenMsg, realSize)
		return
	}
	sendBuf := make([]byte, 4)
	binary.LittleEndian.PutUint32(sendBuf, uint32(realSize))
	n, err := t.Conn.Write(sendBuf)
	if n != 4 {
		err = fmt.Errorf("发送数据长度不等于4个字节")
		return
	}
	if err != nil {
		err = fmt.Errorf("t.Conn.Write(sendBuf) err, %v", err)
		return
	}
	n, err = t.Conn.Write(byteMsg)

	if realSize != n {
		err = fmt.Errorf("发送数据长度不等于实际长度")
		return
	}
	if err != nil {
		err = fmt.Errorf("t.Conn.Write(byteMsg) err, %v", err)
		return
	}
	return
}
